﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace HistogramControlTest.Controls
{
    /// <summary>
    /// 柱状图控件
    /// </summary>
    public class HistogramControl : Control
    {
        #region 常量
        /// <summary>
        /// 柱子的最大高度
        /// </summary>
        public const double MaxRectHeight = 80.0;
        /// <summary>
        /// 当控件值不等于零时，柱子的最小高度为1.0
        /// </summary>
        private const double MinRectHeight = 1.0;

        /// <summary>
        /// 柱子宽窄两种宽度
        /// </summary>
        public const double WideWidth = 12.0;
        public const double NarrowWidth = 5.0;
        #endregion

        #region 变量
        private bool _isShowText;
        private bool _isChecked;
        private bool _isWide;
        private bool _isShowTop;

        private Grid _rootGrid;
        private Grid _rectGrid;
        private Rectangle _centerRect;
        private Storyboard _enterStoryboard;
        private Storyboard _leaveStoryboard;
        private Storyboard _checkStoryboard;
        private Storyboard _uncheckStoryboard;

        private Storyboard _enterRectStoryboard;
        private Storyboard _leaveRectStoryboard;
        private Storyboard _checkRectStoryboard;
        private Storyboard _uncheckRectStoryboard;
        #endregion

        #region 构造函数
        public HistogramControl()
            : this(ShowFormat.Normal, 1.0)
        {

        }

        public HistogramControl(string pFormat, double pScale)
        {
            DefaultStyleKey = typeof(HistogramControl);

            TxtFormat = pFormat ?? ShowFormat.Normal;            
            Scale = pScale.CompareTo(1.0) <= 0 ? 1.0 : pScale;

            IsShowText = true;
            IsOperable = false;
            IsWide = true;
            IsShowTop = true;
            //RectBackground = ResourceDictionaryManager.GetResource<Brush>("XHistogramBackground2");
        }
        #endregion

        #region 重写OnApplyTemplate方法

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _rootGrid = GetTemplateChild("XRootGrid") as Grid;
            _rectGrid = GetTemplateChild("XRectGrid") as Grid;
            _centerRect = GetTemplateChild("XCenterRect") as Rectangle;

            if (_rootGrid != null)
            {
                _enterStoryboard = _rootGrid.Resources["XEnterStoryboard"] as Storyboard;
                _leaveStoryboard = _rootGrid.Resources["XLeaveStoryboard"] as Storyboard;
                _checkStoryboard = _rootGrid.Resources["XCheckStoryboard"] as Storyboard;
                _uncheckStoryboard = _rootGrid.Resources["XUncheckStoryboard"] as Storyboard;

                _enterRectStoryboard = _rootGrid.Resources["XEnterRectStoryboard"] as Storyboard;
                _leaveRectStoryboard = _rootGrid.Resources["XLeaveRectStoryboard"] as Storyboard;
                _checkRectStoryboard = _rootGrid.Resources["XCheckRectStoryboard"] as Storyboard;
                _uncheckRectStoryboard = _rootGrid.Resources["XUncheckRectStoryboard"] as Storyboard;

                if (!IsShowTop)
                {
                    _rootGrid.MouseEnter += OnRootGrid_MouseEnter;
                    _rootGrid.MouseLeftButtonDown += OnRootGrid_MouseLeftButtonDown;
                }
            }
            if (_rectGrid != null && IsOperable)
            {
                _rectGrid.MouseEnter += OnRectGrid_MouseEnter;
                _rectGrid.MouseLeave += OnRectGrid_MouseLeave;
                _rectGrid.MouseLeftButtonDown += OnRectGrid_MouseLeftButtonDown;
            }
            if (_checkStoryboard != null && IsChecked)
            {
                _checkStoryboard.Begin();
            }
        }
        #endregion

        #region 属性
        /// <summary>
        /// 自定义ID标识
        /// </summary>
        public string CustomId { get; set; }
        /// <summary>
        /// 显示数字的格式
        /// </summary>
        public string TxtFormat { get; set; }

        /// <summary>
        /// 控件实际高度
        /// </summary>
        public double FactHeight { get; private set; }

        /// <summary>
        /// 柱子缩放的比例
        /// </summary>
        public double Scale { get; set; }

        /// <summary>
        /// 圆圈的大小
        /// </summary>
        public double RoundSize { get; private set; }

        /// <summary>
        /// 是否显示底部文字
        /// </summary>
        public bool IsShowText
        {
            get { return _isShowText; }
            set
            {
                _isShowText = value;
                RoundSize = value ? RectHeight + 65.0 : RectHeight + 50.0;
                TextVisible = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        /// <summary>
        /// 是否可以操作
        /// </summary>
        public bool IsOperable { get; set; }

        /// <summary>
        /// 是否被选中
        /// </summary>
        public bool IsChecked
        {
            get { return _isChecked; }
            set
            {
                if (value)
                {
                    if (_checkStoryboard != null)
                        _checkStoryboard.Begin();
                }
                else
                {
                    if (_uncheckStoryboard != null)
                        _uncheckStoryboard.Begin();
                }
                _isChecked = value;
            }
        }

        /// <summary>
        /// 是否以较宽的方式显示柱子
        /// </summary>
        public bool IsWide
        {
            get { return _isWide; }
            set
            {
                _isWide = value;
                RectWidth = value ? WideWidth : NarrowWidth;
            }
        }

        /// <summary>
        /// 是否显示头部数值
        /// </summary>
        public bool IsShowTop
        {
            get { return _isShowTop; }
            set
            {
                _isShowTop = value;
                BkRectHeight = value ? 0.0 : 10.0;
            }
        }

        /// <summary>
        /// 柱状图在组中的索引
        /// </summary>
        public int Index { get; set; }

        /// <summary>
        /// 控件中部（柱子）
        /// </summary>
        public Rectangle CenterRect
        {
            get { return _centerRect; }
        }
        #endregion

        #region 依赖属性
        /// <summary>
        /// 控件值
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set
            {
                if (value < 0.0)
                {
                    throw new ArgumentOutOfRangeException("value", @"柱状图的值不能小于0！");
                }
                SetValue(ValueProperty, value);

                TxtValue = TxtFormat == ShowFormat.Percent ? value.ToString(ShowFormat.Decimal) + "%" : value.ToString(TxtFormat);
                RectHeight = value / Scale;
            }
        }

        /// <summary>
        /// 柱子的高度
        /// </summary>
        public double RectHeight
        {
            get { return (double)GetValue(RectHeightProperty); }
            private set
            {
                if (value < MinRectHeight && value > 0.0000001)
                {
                    value = MinRectHeight;
                }
                SetValue(RectHeightProperty, value);

                FactHeight = value + 35.0;
                RoundSize = IsShowText ? value + 65.0 : value + 50.0;
            }
        }

        /// <summary>
        /// 柱子的宽度
        /// </summary>
        public double RectWidth
        {
            get { return (double)GetValue(RectWidthProperty); }
            set { SetValue(RectWidthProperty, value); }
        }

        /// <summary>
        /// 头部显示的文本值
        /// </summary>
        public string TxtValue
        {
            get { return (string)GetValue(TxtValueProperty); }
            private set { SetValue(TxtValueProperty, value); }
        }

        /// <summary>
        /// 柱子的背景色
        /// </summary>
        public Brush RectBackground
        {
            get { return (Brush)GetValue(RectBackgroundProperty); }
            set { SetValue(RectBackgroundProperty, value); }
        }

        /// <summary>
        /// 底部显示的文字
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        /// <summary>
        /// 背景矩形的高度
        /// </summary>
        public double BkRectHeight
        {
            get { return (double)GetValue(BkRectHeightProperty); }
            set { SetValue(BkRectHeightProperty, value); }
        }

        /// <summary>
        /// 柱子的提示信息
        /// </summary>
        public string RectTooltip
        {
            get { return (string)GetValue(RectTooltipProperty); }
            set { SetValue(RectTooltipProperty, value); }
        }

        /// <summary>
        /// 显示/隐藏底部文字
        /// </summary>
        public Visibility TextVisible
        {
            get { return (Visibility)GetValue(TextVisibleProperty); }
            set { SetValue(TextVisibleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TextVisible.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextVisibleProperty =
            DependencyProperty.Register("TextVisible", typeof(Visibility), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for RectTooltip.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RectTooltipProperty =
            DependencyProperty.Register("RectTooltip", typeof(string), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for BkRectHeight.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BkRectHeightProperty =
            DependencyProperty.Register("BkRectHeight", typeof(double), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for RectBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RectBackgroundProperty =
            DependencyProperty.Register("RectBackground", typeof(Brush), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for TxtValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TxtValueProperty =
            DependencyProperty.Register("TxtValue", typeof(string), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for RectWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RectWidthProperty =
            DependencyProperty.Register("RectWidth", typeof(double), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for RectHeight.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RectHeightProperty =
            DependencyProperty.Register("RectHeight", typeof(double), typeof(HistogramControl), null);

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(HistogramControl), null);
        #endregion

        #region 鼠标操作
        /// <summary>
        /// 鼠标移入控件触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRectGrid_MouseEnter(object sender, MouseEventArgs e)
        {
            if (_enterStoryboard != null && !IsChecked)
                _enterStoryboard.Begin();
        }

        /// <summary>
        /// 鼠标移出控件触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRectGrid_MouseLeave(object sender, MouseEventArgs e)
        {
            if (_leaveStoryboard != null && !IsChecked)
                _leaveStoryboard.Begin();
        }

        /// <summary>
        /// 按下鼠标左键触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRectGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (IsChecked)
                return;

            IsChecked = true;
            if (HistogramChecked != null)
                HistogramChecked(this);
        }

        /// <summary>
        /// 鼠标移入柱状矩形触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRootGrid_MouseEnter(object sender, MouseEventArgs e)
        {
            if (HistogramMouseEnter != null)
                HistogramMouseEnter(this);

            if (_enterRectStoryboard != null)
                _enterRectStoryboard.Begin();
        }

        /// <summary>
        /// 按下鼠标左键触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRootGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (HistogramMouseClick != null)
                HistogramMouseClick(this);

            if (_checkRectStoryboard != null)
                _checkRectStoryboard.Begin();
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 恢复柱状矩形状态
        /// </summary>
        public void ResetRectState()
        {
            if (_uncheckRectStoryboard != null && !IsShowTop)
            {
                _leaveRectStoryboard.Begin();
                _uncheckRectStoryboard.Begin();
            }
        }
        #endregion

        #region 事件
        /// <summary>
        /// 控件选中事件
        /// </summary>
        public event Action<HistogramControl> HistogramChecked;

        /// <summary>
        /// 鼠标移入控件事件
        /// </summary>
        public event Action<HistogramControl> HistogramMouseEnter;
        /// <summary>
        /// 鼠标点击控件事件
        /// </summary>
        public event Action<HistogramControl> HistogramMouseClick;
        #endregion
    }

    /// <summary>
    /// 显示数字的格式
    /// </summary>
    public class ShowFormat
    {
        /// <summary>
        /// 用分号隔开的数字格式
        /// </summary>
        public const string Normal = "N0";
        /// <summary>
        /// 百分数格式
        /// </summary>
        public const string Percent = "P0";
        /// <summary>
        /// 保留两位小数
        /// </summary>
        public const string Decimal = "F2";
    }
}
